package com.java.Map;

import java.util.*;

public class MapAPI {
    public static <T extends Map> T put(T t) {
        System.out.println(t.put(3, "A")); // null
        System.out.println(t.put(1, "A")); // null
        System.out.println(t.put(2, "BB")); // null
        System.out.println(t.put(2, "B")); // BB
        return t;
    }
    
    public static <T extends Map> T putAll(T t) throws InstantiationException, IllegalAccessException {
        Map map = t.getClass().newInstance();
        map.put(6, "C");
        map.put(4, "C");
        map.put(5, "D");
        
        t.putAll(map);
        return t;
    }
    
    public static <T extends Map> T putIfAbsent(T t) {
        System.out.println(t.putIfAbsent(6, "E")); // C
        System.out.println(t.putIfAbsent(7, "E")); // null
        return t;
    }
    
    public static <T extends Map> void get(T t) {
        System.out.println(t.get(7)); // E
        System.out.println(t.get(8)); // null
    }
    
    public static <T extends Map> void getOrDefault(T t) {
        System.out.println(t.getOrDefault(7, "Default")); // E
        System.out.println(t.getOrDefault(8, "Default")); // Default
    }
    
    public static <T extends Map> T remove(T t) {
        System.out.println(t.remove(7)); // E
        System.out.println(t.remove(8)); // null
        return t;
    }
    
    public static <T extends Map> T replace(T t) {
        System.out.println(t.replace(6, "E")); // C
        System.out.println(t.replace(7, "E")); // null
        return t;
    }
    
    public static <T extends Map> void containsKey(T t) {
        try {
            System.out.println(t.containsKey(6)); // true
            System.out.println(t.containsKey("A")); // false
        } catch (ClassCastException e) {
            System.out.println("TreeMap：" + e.getMessage()); // java.lang.Integer cannot be cast to java.lang.String
        }
    }
    
    public static <T extends Map> void containsValue(T t) {
        System.out.println(t.containsValue(6)); // false
        System.out.println(t.containsValue("A")); // true
    }
    
    public static void main(String[] args) throws InstantiationException, IllegalAccessException {
        HashMap hashMap = new HashMap();
        LinkedHashMap linkedHashMap = new LinkedHashMap();
        TreeMap treeMap = new TreeMap();
        Properties properties = new Properties();
        
        // put：添加一个键值对到集合，返回值表示原集合被替换的键值对中的值，若无被替换的键值对则返回null
        System.out.println(put(hashMap)); // {1=A, 2=B, 3=A}
        System.out.println(put(linkedHashMap)); // {3=A, 1=A, 2=B}
        System.out.println(put(treeMap)); // {1=A, 2=B, 3=A}
        System.out.println(put(properties)); // {3=A, 2=B, 1=A}
        
        // putAll：添加多个键值对到集合，无返回值
        System.out.println(putAll(hashMap)); // {1=A, 2=B, 3=A, 4=C, 5=D, 6=C}
        System.out.println(putAll(linkedHashMap)); // {3=A, 1=A, 2=B, 6=C, 4=C, 5=D}
        System.out.println(putAll(treeMap)); // {1=A, 2=B, 3=A, 4=C, 5=D, 6=C}
        System.out.println(putAll(properties)); // {6=C, 5=D, 4=C, 3=A, 2=B, 1=A}
        
        // putIfAbsent：当该键值对中的键不存在于集合中则添加该键值对到集合，返回值表示原集合已存在键值对中的值，若不存在该键值对中的键则返回null
        System.out.println(putIfAbsent(hashMap)); // {1=A, 2=B, 3=A, 4=C, 5=D, 6=C, 7=E}
        System.out.println(putIfAbsent(linkedHashMap)); // {3=A, 1=A, 2=B, 6=C, 4=C, 5=D, 7=E}
        System.out.println(putIfAbsent(treeMap)); // {1=A, 2=B, 3=A, 4=C, 5=D, 6=C, 7=E}
        System.out.println(putIfAbsent(properties)); // {7=E, 6=C, 5=D, 4=C, 3=A, 2=B, 1=A}
        
        // get：获取集合指定键值对中键的值，返回值表示获取到的键值对中的值，若不存在该键值对中的键则返回null
        get(hashMap);
        get(linkedHashMap);
        get(treeMap);
        get(properties);
        
        // getOrDefault：获取集合指定键值对中键的值，返回值表示获取到的键值对中的值，若不存在该键值对中的键则返回默认值
        getOrDefault(hashMap);
        getOrDefault(linkedHashMap);
        getOrDefault(treeMap);
        getOrDefault(properties);
        
        // remove：移除集合指定键值对中键的键值对，返回值表示原集合被移除的键值对中的值，若无被移除的键值对则返回null
        System.out.println(remove(hashMap)); // {1=A, 2=B, 3=A, 4=C, 5=D, 6=C}
        System.out.println(remove(linkedHashMap)); // {3=A, 1=A, 2=B, 6=C, 4=C, 5=D}
        System.out.println(remove(treeMap)); // {1=A, 2=B, 3=A, 4=C, 5=D, 6=C}
        System.out.println(remove(properties)); // {6=C, 5=D, 4=C, 3=A, 2=B, 1=A}
        
        // replace：替换集合指定键值对中键的值，返回值表示原集合被替换的键值对中的值，若无被替换的键值对则返回null
        System.out.println(replace(hashMap)); // {1=A, 2=B, 3=A, 4=C, 5=D, 6=E}
        System.out.println(replace(linkedHashMap)); // {3=A, 1=A, 2=B, 6=E, 4=C, 5=D}
        System.out.println(replace(treeMap)); // {1=A, 2=B, 3=A, 4=C, 5=D, 6=E}
        System.out.println(replace(properties)); // {6=E, 5=D, 4=C, 3=A, 2=B, 1=A}
        
        // containsKey：判断集合内是否存在指定键，重写hashCode和equals可自定义判断方式
        containsKey(hashMap);
        containsKey(linkedHashMap);
        containsKey(treeMap);
        containsKey(properties);
        
        // containsValue：判断集合内是否存在指定值，重写hashCode和equals可自定义判断方式
        containsValue(hashMap);
        containsValue(linkedHashMap);
        containsValue(treeMap);
        containsValue(properties);
        
        // isEmpty：判断集合内键值对个数是否为空
        System.out.println(hashMap.isEmpty()); // false
        System.out.println(linkedHashMap.isEmpty()); // false
        System.out.println(treeMap.isEmpty()); // false
        System.out.println(properties.isEmpty()); // false
        
        // size：获取集合内键值对总数
        System.out.println(hashMap.size()); // 6
        System.out.println(linkedHashMap.size()); // 6
        System.out.println(treeMap.size()); // 6
        System.out.println(properties.size()); // 6
        
        // clear：清空集合内所有键值对，无返回值
        hashMap.clear();
        System.out.println(hashMap); // {}
        linkedHashMap.clear();
        System.out.println(linkedHashMap); // {}
        treeMap.clear();
        System.out.println(treeMap); // {}
        properties.clear();
        System.out.println(properties); // {}
    }
}
